home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 51
/
Amiga Format CD51 (2000-03-10)(Future Publishing)(GB)[!][issue 2000-04].iso
/
-in_the_mag-
/
banging_the_metal
/
qdos
/
qdos4amiga2
/
romsrc
/
ace
/
ace_asm
Wrap
Text File
|
2000-01-03
|
25KB
|
1,098 lines
*
* last modified 02/09/97
*
* AMIGA QDOS SCREEN ACCELERATOR for 32 bit AGA machines
*
* New version supports FLASH in MODE 8 - CPU-intensive!
* Inner loop no longer fits the 68030 cache if flashing.
*
* Version 3.25 by Simon N Goodwin, with thanks to Mark
* J Swift for scanning a listing when I lost the source!
* Listing assumes TABs set to 11 chars
*
qdos equr a0 Qdos screen pointer
Plane1 equr a1 Least significant bitplane
Plane2 equr a2
Plane3 equr a3 MODE 8 only
table equr a4 Byte translator
*
* Interrupt servers must preserve A5, A6 and A7 (!)
* but all other registers are up for grabs.
*
* Bitplane accumulator registers, added in v3.11
*
RED equr d4
BLUE equr d5
GREEN equr d6
*
* Amiga hardware equates
*
COLOR00 EQU $DFF180
COLOR01 EQU $DFF182
COLOR02 EQU $DFF184
COLOR03 EQU $DFF186
COLOR04 EQU $DFF188
COLOR05 EQU $DFF18A
COLOR06 EQU $DFF18C
COLOR07 EQU $DFF18E
*
* QDOS equates
*
BP.INIT equ $110
CA.GTINT equ $112
BV.CHRIX equ $11A
*
* QDOS hardware equates
*
MC_STAT equ $18063
FLASH_PERIOD equ 16 Fleids per flash change
*
* Default addresses for Qdos and Amiga screen images
*
qlbase equ $20000 Base of first QL screen
qlsize equ $8000 Size of each QL screen
bp1base equ $10000 Base of first Amiga bitplane
bp3base equ $12000 Base of BLUE bitplane in MODE 8
bp2base equ $14000 Base of second bitplane
*
* Offsets of variables in interrupt linkage
*
link equ 0 Interrupt link comes first
vector equ 4 Offset of code address
marker equ 8 Offset of "ACE3" signature
prefix equ 12 Number of bytes so far
*
* These variables follow MARKER and are relative to PREFIX
*
limit equ 0 Count fields down from this
count equ 1 Current field in sequence
busy equ 2 Set during interrupt handler
missed equ 3 (Counted interrupts ignored)
chunks equ 4 Number of 2K chunks at each pass
soFar equ 5 Number of 2K chunks already done
smode equ 6 current screen mode
flash_now equ 7 Non zero for flash fields
flash_tick equ 8 Counts down between flashes
flash_rate equ 9 Number of fields between flashes
varSize equ prefix+10 Total bytes of linkage
*
* ROM header
*
BASE:
dc.l $4AFB0001 ROM recognition code
dc.w define-BASE BASIC procs
dc.w ROM_START-BASE
dc.b 0,30,'ACE screen accelerator v3.26 ',$A
*
* start of ROM code
*
ROM_START:
movem.l d0-d3/a0-a3,-(a7)
lea BASE(pc),a0
cmp.l #$1000000,a0 FAST RAM?
bmi ROM_EXIT No, user decides
moveq #0,d0
trap #1
move.b 161(a0),d0 Check CPU version
cmp.b #$30,d0 < 030, user decides
bcs.s ROM_EXIT
bsr mblit_on
ROM_EXIT:
movem.l (a7)+,d0-d3/a0-a3
rts
*
* This is the routine that redraws the whole screen
* On entry A3 -> Linkage-8; A6 -> Qdos variables
*
AceVars equ prefix+8 A3 offset to LIMIT
*
redraw:
btst #7,$1813E
beq mblit_off
tst.b busy+AceVars(a3) Prevent re-entrancy
beq.s update
*
* Code to work out the number of interrupts MISSED (while ACE is
* busy) commented out for version 3.16 as Qdos can't cope with
* missed interrupts anyway, and I needed the variable to set the
* proportion of the screen to be updated (1..16, as SCR_PRIORITY)
*
* ignore addq.b #1,missed+AceVars(a3)
skip:
rts
*
update:
move.b flash_rate+AceVars(a3),d1
beq.s limit_ok Not ever flashing!
subq.b #1,flash_tick+AceVars(a3)
bne.s limit_ok No change
move.b d1,flash_tick+AceVars(a3)
not.b flash_now+AceVars(a3) Toggle flash flag
* move.b missed+AceVars(a3),d1
* beq.s limit_ok No interrupts missed
*
* addq.b #1,d1 Count one that worked
* clr.b missed+AceVars(a3) Keep checking
* cmp.b limit+AceVars(a3),d1 Can the CPU keep up?
* bls.s limit_ok There is enough time
*
* move.b d1,limit+AceVars(a3) Increase limit
*
limit_ok:
subq.b #1,count+AceVars(a3)
bne.s skip The time is NOT nigh
*
st busy+AceVars(a3) Flag critical region
move.b limit+AceVars(a3),count+AceVars(a3)
lea.l bp1base,Plane1
lea.l bp2base,Plane2
lea.l qlbase+qlsize,qdos Point at screen 2
move.b MC_STAT,d2 Check if it's in use
bmi.s chkmod
*
lea.l -qlsize(qdos),qdos Wind back to screen 1
*
* Check if mode has changed
*
chkmod:
cmp.b smode+AceVars(a3),d2
beq.s chksho
*
bsr ace_cop
move.b d2,smode+AceVars(a3)
*
chksho:
btst #1,d2 check blanking bit
bne done and exit if set
*
* Work out which chunk needs to be updated next, and adjust pointers
*
based:
move.w #2048/8,d3 Iterations per 2K chunk
moveq #0,d4
move.b chunks+AceVars(a3),d4
moveq #0,d5
move.b soFar+AceVars(a3),d5
*
* Advance input and output pointers past data previously processed
*
move.l d5,d6
lsl.l #8,d6
add.l d6,d6 * 512 for output offsets
add.l d6,Plane1
add.l d6,qdos
add.l d6,Plane2
add.l d6,qdos Qdos gets scanned fastest
add.l d6,qdos
add.l d6,qdos We'll need D6 again later
*
* Work out where we're going to end up
*
add.b d4,d5
cmp.b #16,d5 Up to end of screen?
bcs.s nextChunk
*
sub.b #16,d5 Compute potential overrun
sub.b d5,d4 Do that much less, then
clr.b d5 Restart at the beginning
*
nextChunk:
move.b d5,soFar+AceVars(a3)
mulu.w d4,d3 D3 is loop count, D3.H=0
subq.w #1,d3 Adjust for DBRA
* move.w #6,$DFF180 Show beam position
*
* If we're running on a CPU with a data cache, we should disable cache
* allocation while redrawing the screen to avoid swamping it with data
* that we do not intend to re-use, and wiping out MODE 8 table data.
*
move.b 161(a6),d0 Check CPU version
cmp.b #$30,d0
bcs.s decached No data cache before 68030
*
* If we're in MODE 8 we need to prime the data cache with our byteTable
*
btst #3,d2 MODE 8 ?
beq.s noPrime
*
lea.l byteTable(pc),table
moveq #256/4-1,d1
primer:
tst.l (table)+ Get it all into the cache
dbra d1,primer
*
noPrime:
dc.w $4E7A,$1002 MOVEC CACR,D1
cmp.b #$30,d0 Is this a 68030?
bne.s after030
*
* 68030 data cache disabling code
*
btst #8,d1
beq mblit_off disable if instr cache off
move.l d1,d7 Save old setting
* beq.s decached
*
bset #9,d1 Disable data allocation
dc.w $4E7B,$1002 MOVEC D1,CACR
bra.s decached
*
* 68040/060 data cache disabling code; leaves prior DTT0 in D7
*
after030:
btst #15,d1
beq mblit_off disable if instr cache off
dc.w $4E7A,$7006 MOVEC DTT0,D7
move.l #$C060,d1 Don't cache 0..16 Mb
dc.w $4E7B,$1006 MOVEC D1,DTT0
*
* Check the mode to determine the format of the Qdos screen
*
decached:
btst #3,d2 Mode 8 ?
bne.s mode8
*
* Algorithmic version, reads 8 bytes and unscrambles them to 2 bitplanes
* Input read to D0 and D5 goes to D2 and D3; D4 scratch, D6 counts loops
*
mode4:
move.w d3,d1
add.l d6,Plane1 MODE 4 outputs 2 for 1
add.l d6,Plane2
*
next8:
movem.l (qdos)+,d0/d5 Scrambled long words: ABCD EFGH
move.l d0,d2 Set A in high byte of result
lsl.l #8,d0 Align BC in the high word
move.l d2,d4 Save low byte in D for later
swap d0 Low word is now BC
swap d2 CDAB
move.l d0,d3 Set up B, but in low word
move.b d4,d3 Set up D, again low for now
move.b d0,d2 AC set in low word
*
* So far we have set AC and BD in the low word of our output registers
* Next step is to work out the other word, and get both words in order
*
move.l d5,d4 Save H for later
swap d5 GHEF
swap d2 AC??
move.w d5,d2 Set E in place
move.l d4,d5 EFGH
lsr.l #8,d5 0EFG
move.b d5,d2 Set G in place
move.l d2,(Plane2)+ Store ACEG green bits
swap d3 BD??
move.w d5,d3 BDF?
move.b d4,d3 BDFH
move.l d3,(Plane1)+ Write out red bits
dbra d1,next8
*
bra CacheIn
*
* MODE 8 support - added in version 3.11
*
mode8:
lea.l byteTable(pc),table Point to start of table
tst.b flash_now+AceVars(a3)
bne do_flash
*
mode8_nf:
moveq #0,d0 Ensure byte values are unsigned longs
move.l a3,-(a7)
lea.l bp3base,Plane3 Extra plane pointer for eight colours
add.l d6,Plane3
*
next2:
move.l (qdos)+,d1
*
* Convert two Qdos screen bytes into three packed nybbles for the bitplanes
*
rol.l #8,d1 Move MSB (green byte) to LSB
move.b d1,d0 Make it an unsigned long value
moveq #15,d2 Mask for low nybble
and.b 0(table,d0.l),d2 Get four packed green bits
lsl.l #4,GREEN Make room
or.b d2,GREEN
rol.l #8,d1 Get blue and red byte to LSB
move.b d1,d0
moveq #15,d2 Mask for packed red bits
move.b 0(table,d0.l),d0
lsl.l #4,RED Make room
and.b d0,d2 Extract red bits
lsl.l #4,BLUE Make room
lsr.b #4,d0 Move blue pack to low nybble
or.b d2,RED
or.b d0,BLUE
*
* Now do the next two Qdos bytes, from the other half of D1
*
rol.l #8,d1 Move MSB (green byte) to LSB
move.b d1,d0 Make it an unsigned long value
moveq #15,d2 Mask for low nybble
and.b 0(table,d0.l),d2 Get four packed green bits
lsl.l #4,GREEN Make room
or.b d2,GREEN
rol.l #8,d1 Get blue and red byte to LSB
move.b d1,d0
moveq #15,d2 Mask for packed red bits
move.b 0(table,d0.l),d0
lsl.l #4,RED Make room
and.b d0,d2 Extract red bits
lsl.l #4,BLUE Make room
lsr.b #4,d0 Move blue pack to low nybble
or.b d2,RED
or.b d0,BLUE
*
* Pick up another Qdos long word and repeat to get a whole word for each bitplane
*
move.l (qdos)+,d1
*
* Optimisation to speed up black areas of the screen. Overhead is just this test
*
beq.s blackOut Skip prevarication
*
rol.l #8,d1 Move MSB (green byte) to LSB
move.b d1,d0 Make it an unsigned long value
moveq #15,d2 Mask for low nybble
and.b 0(table,d0.l),d2 Get four packed green bits
lsl.l #4,GREEN Make room
or.b d2,GREEN
rol.l #8,d1 Get blue and red byte to LSB
move.b d1,d0
moveq #15,d2 Mask for packed red bits
move.b 0(table,d0.l),d0
lsl.l #4,RED Make room
and.b d0,d2 Extract red bits
lsl.l #4,BLUE Make room
lsr.b #4,d0 Move blue pack to low nybble
or.b d2,RED
or.b d0,BLUE
*
* Time to sort out the remaining Qdos word
*
rol.l #8,d1 Move MSB (green byte) to LSB
move.b d1,d0 Make it an unsigned long value
moveq #15,d2 Mask for low nybble
and.b 0(table,d0.l),d2 Get four packed green bits
lsl.l #4,GREEN Make room
or.b d2,GREEN
*
* If D3 is even we've got long words to write out
*
btst #0,d3
bne.s noWrite
*
* These three nybbles complete long bitplane values which must be stored
*
move.l GREEN,(Plane3)+
rol.l #8,d1 Get blue and red byte to LSB
move.b d1,d0
moveq #15,d2 Mask for packed red bits
move.b 0(table,d0.l),d0
lsl.l #4,RED Make room
and.b d0,d2 Extract red bits
or.b d2,RED
move.l RED,(Plane2)+
lsl.l #4,BLUE Make room
lsr.b #4,d0 Move blue pack to low nybble
or.b d0,BLUE
move.l BLUE,(Plane1)+
bra.s CarryOn
*
* A quick hack to save time if even input long words are zero (8 black pixels)
*
blackOut:
lsl.l #8,GREEN
lsl.l #8,RED
lsl.l #8,BLUE
*
* If D3 is even we've got long words to write out
*
btst #0,d3
bne.s CarryOn Go round again for the next word
*
move.l BLUE,(Plane1)+
move.l RED,(Plane2)+
move.l GREEN,(Plane3)+
bra.s CarryOn
*
* Continue to accumulate in registers as we have not yet got long values
*
noWrite:
rol.l #8,d1 Get blue and red byte to LSB
move.b d1,d0
moveq #15,d2 Mask for packed red bits
move.b 0(table,d0.l),d0
lsl.l #4,RED Make room
and.b d0,d2 Extract red bits
lsl.l #4,BLUE Make room
lsr.b #4,d0 Move blue pack to low nybble
or.b d2,RED
or.b d0,BLUE
CarryOn:
dbra d3,next2
move.l (a7)+,a3 Restore -> AceVars
*
CacheIn:
move.b 161(a6),d1 Check for data cache
cmp.b #$30,d1 68030?
bcs.s done
*
beq.s enable030
*
* Revert to prior setting of DTT0 on 68040 or 68060
*
dc.w $4E7B,$7006 MOVEC D7,DTT0
bra.s done
*
* Revert to prior setting of CACR on 68030
*
enable030:
dc.w $4E7B,$7002 MOVEC D7,CACR
done:
clr.b busy+AceVars(a3)
* move.w #0,$DFF180 Show beam position
rts
*
* New routine for v3.22 to render a (potentially) flashing field
*
do_flash:
moveq #0,d0 Ensure byte values are unsigned longs
move.l a3,-(a7)
lea.l bp3base,Plane3 Extra plane pointer for eight colours
move.l d7,-(a7) More scratch space needed
add.l d6,Plane3
*
Fnext2:
move.l (qdos)+,d1
*
* Check for flash bits and process them if necessary
*
* Optimisation for no change in this long word
move.l #$55005500,d2 Mask for just the flash bits
and.l d1,d2
beq.s No_bits1 Skip if no flash bits set
moveq #30,d0 First flast bit # to test
move.l #$7F3FFFFF,d2 Mask excludes first pixel colour
Flash1:
btst d0,d1 New flash bit set?
bne.s Toggle1
tst.l d3 Same as what?
bpl.s Pixel1
Tweak1:
ror.l #2,d7 Push colour mask along
and.l d2,d1 Obscure old colour of pixel
or.l d7,d1 Replace with flash colour
Pixel1:
ror.l #2,d2 Next pixel mask (?)
bpl.s Done1 Back to the start!
subq.b #2,d0 Next flash bit
cmp.b #22,d0
bne.s Flash1
ror.l #8,d2 Move mask over odd RB byte
ror.l #8,d7 Just in case flashing now
subq.b #8,d0
bra.s Flash1
Toggle1:
bchg #31,d3 Toggle flag in MS bit
bne.s Tweak1 Once more with feeling
move.l d2,d7
not.l d7 Mask for pixel colour
and.l d1,d7
bra.s Pixel1
No_bits1:
tst.l d3 MS bit set if flashing NOW
bpl.s Flashed1
*
* A whole line of eight flashing pixels - do these the quick way!
*
lsl.l #8,RED
btst #25,d7 Red bit set in background?
sne RED If so, set eight red bits
lsl.l #8,GREEN
btst #1,d7 Green bit
sne GREEN
lsl.l #8,BLUE Make room for 8 blue bits
btst #24,d7
sne BLUE
bra.s Byten1 Skip to next fetch
Done1 ror.l #8,d7 Colour back to top bits
*
* Convert two Qdos screen bytes into three packed nybbles for the bitplanes
*
Flashed1:
rol.l #8,d1 Move MSB (green byte) to LSB
move.b d1,d0 Make it an unsigned long value
moveq #15,d2 Mask for low nybble
and.b 0(table,d0.l),d2 Get four packed green bits
lsl.l #4,GREEN Make room
or.b d2,GREEN
rol.l #8,d1 Get blue and red byte to LSB
move.b d1,d0
moveq #15,d2 Mask for packed red bits
move.b 0(table,d0.l),d0
lsl.l #4,RED Make room
and.b d0,d2 Extract red bits
lsl.l #4,BLUE Make room
lsr.b #4,d0 Move blue pack to low nybble
or.b d2,RED
or.b d0,BLUE
*
* Now do the next two Qdos bytes, from the other half of D1
*
rol.l #8,d1 Move MSB (green byte) to LSB
move.b d1,d0 Make it an unsigned long value
moveq #15,d2 Mask for low nybble
and.b 0(table,d0.l),d2 Get four packed green bits
lsl.l #4,GREEN Make room
or.b d2,GREEN
rol.l #8,d1 Get blue and red byte to LSB
move.b d1,d0
moveq #15,d2 Mask for packed red bits
move.b 0(table,d0.l),d0
lsl.l #4,RED Make room
and.b d0,d2 Extract red bits
lsl.l #4,BLUE Make room
lsr.b #4,d0 Move blue pack to low nybble
or.b d2,RED
or.b d0,BLUE
*
* Pick up another long word and repeat to get a whole word for each bitplane
*
Byten1:
move.l (qdos)+,d1
*
* Check for flash bits and process them if necessary (v3.22 extension)
*
move.l #$55005500,d2 Mask for just the flash bits
and.l d1,d2
beq.s No_bits2 Skip if no flash bits set
moveq #30,d0 First flast bit # to test
move.l #$7F3FFFFF,d2 Mask excludes first pixel colour
Flash2:
btst d0,d1 New flash bit set?
bne.s Toggle2
tst.l d3 Same as what?
bpl.s Pixel2
Tweak2:
ror.l #2,d7 Push colour mask along
and.l d2,d1 Obscure old colour of pixel
or.l d7,d1 Replace with flash colour
Pixel2:
ror.l #2,d2 Next pixel mask (?)
bpl.s Done2 Back to the start!
subq.b #2,d0 Next flash bit
cmp.b #22,d0
bne.s Flash2
ror.l #8,d2 Move mask over odd RB byte
ror.l #8,d7 Just in case flashing now
subq.b #8,d0
bra.s Flash2
Toggle2:
bchg #31,d3 Toggle flag in MS bit
bne.s Tweak2 Last flash in this set
move.l d2,d7
not.l d7 Mask for pixel colour
and.l d1,d7
bra.s Pixel2
No_bits2:
tst.l d3 MS bit set if flashing NOW
bpl.s Flashed2
*
* A whole line of eight flashing pixels - do these the quick way!
*
lsl.l #8,RED
btst #25,d7 Red bit set in background?
sne RED If so, set eight red bits
lsl.l #8,GREEN
btst #1,d7 Green bit before rotation
sne GREEN
lsl.l #8,BLUE Make room for 8 blue bits
btst #24,d7
sne BLUE
bra.s Byten2
Done2:
ror.l #8,d7 Colour back to top bits
*
* Convert two Qdos screen bytes into three packed nybbles for the bitplanes
*
Flashed2 tst.l d1
*
* Optimisation to speed up black areas of the screen
*
beq.s FblackOut Skip prevarication
rol.l #8,d1 Move MSB (green byte) to LSB
move.b d1,d0 Make it an unsigned long value
moveq #15,d2 Mask for low nybble
and.b 0(table,d0.l),d2 Get four packed green bits
lsl.l #4,GREEN Make room
or.b d2,GREEN
rol.l #8,d1 Get blue and red byte to LSB
move.b d1,d0
moveq #15,d2 Mask for packed red bits
move.b 0(table,d0.l),d0
lsl.l #4,RED Make room
and.b d0,d2 Extract red bits
lsl.l #4,BLUE Make room
lsr.b #4,d0 Move blue pack to low nybble
or.b d2,RED
or.b d0,BLUE
*
* Time to sort out the remaining Qdos word
*
rol.l #8,d1 Move MSB (green byte) to LSB
move.b d1,d0 Make it an unsigned long value
moveq #15,d2 Mask for low nybble
and.b 0(table,d0.l),d2 Get four packed green bits
lsl.l #4,GREEN Make room
or.b d2,GREEN
*
* If D3 is even we've got long words to write out
*
btst #0,d3
bne.s FnoWrite
*
* These three nybbles complete long bitplane values which must be stored
*
move.l GREEN,(Plane3)+
rol.l #8,d1 Get blue and red byte to LSB
move.b d1,d0
moveq #15,d2 Mask for packed red bits
move.b 0(table,d0.l),d0
lsl.l #4,RED Make room
and.b d0,d2 Extract red bits
or.b d2,RED
move.l RED,(Plane2)+
lsl.l #4,BLUE Make room
lsr.b #4,d0 Move blue pack to low nybble
or.b d0,BLUE
*
* Before posting the last write, see if the flash flag needs toggling
*
Fcheck:
moveq #31,d0 Mask for 256 pixel wide plane
move.l Plane3,d1
and.l d1,d0 Test low bits for next write
bne.s in_line
ext.l d3 Reset flash flag, new line
in_line:
move.l BLUE,(Plane1)+
bra.s FCarryOn
*
* Quick tweak saves time if even input long words are zero (8 black pixels)
*
FblackOut:
lsl.l #8,GREEN
lsl.l #8,RED
lsl.l #8,BLUE
Byten2:
btst #0,d3 Have we got a whole long word yet?
bne.s FCarryOn Go round again for the next word
*
move.l RED,(Plane2)+
move.l GREEN,(Plane3)+
bra.s Fcheck
*
* Continue to accumulate in registers as we have not yet got long values
*
FnoWrite:
rol.l #8,d1 Get blue and red byte to LSB
move.b d1,d0
moveq #15,d2 Mask for packed red bits
move.b 0(table,d0.l),d0
lsl.l #4,RED Make room
and.b d0,d2 Extract red bits
lsl.l #4,BLUE Make room
lsr.b #4,d0 Move blue pack to low nybble
or.b d2,RED
or.b d0,BLUE
FCarryOn:
dbra d3,Fnext2
move.l (a7)+,d7
move.l (a7)+,a3
bra.w CacheIn
*
* Subroutine to change copper list to suit ACE
*
ace_cop:
bset #7,$1813E disable screen blitter
move.w #$0000,COLOR00
move.b MC_STAT,d2
btst #3,d2
bne.s ace_cop8
*
ace_cop4:
move.w #76,99974 DDFSTART
move.w #204,99978 DDFSTOP
move.w #-4,99982 Modulo
move.w #-4,99986 Modulo
move.w #$A200,100002
btst #1,d2
bne blnkit
move.w #$0F00,COLOR01
move.w #$00F0,COLOR02
move.w #$0FFF,COLOR03
rts
*
ace_cop8:
move.w #72,99974 DDFSTART
move.w #200,99978 DDFSTOP
move.w #-2,99982 Modulo
move.w #-2,99986 Modulo
move.w #$3200,100002
btst #1,d2
bne.s blnkit
move.w #$000F,COLOR01
move.w #$0F00,COLOR02
move.w #$0F0F,COLOR03
move.w #$00F0,COLOR04
move.w #$00FF,COLOR05
move.w #$0FF0,COLOR06
move.w #$0FFF,COLOR07
rts
*
blnkit:
move.w #$0000,COLOR01
move.w #$0000,COLOR02
move.w #$0000,COLOR03
rts
*
* sub to change copper list to suit blitter
*
blt_cop:
bclr #7,$1813E enable screen blitter
move.w #76,99974 DDFSTART
move.w #204,99978 DDFSTOP
move.w #-4,99982 Modulo
move.w #-4,99986 Modulo
move.w #$A200,100002
move.w #$0000,COLOR00
move.w #$0FFF,COLOR03
*
move.b MC_STAT,d2
btst #1,d2
bne.s blnkit
btst #3,d2
bne.s blt_cop8
*
blt_cop4:
move.w #$0F00,COLOR01
move.w #$00F0,COLOR02
rts
*
blt_cop8:
move.w #$0B44,COLOR01
move.w #$04B4,COLOR02
move.w #$08FF,COLOR03
rts
*
* ACE_ON asks is it already on? if so, return no error
*
mblit_on:
bsr.s find_pos2
beq.s it_worked Already on
*
* Otherwise, allocate linkage area in common heap
*
moveq #varSize,d1
moveq #0,d2 Owned by SuperBASIC
moveq #24,d0 MT.ALCHP trap key
trap #1
tst.l d0 Did we get it?
bne.s oops
*
bsr ace_cop
move.b d2,prefix+smode(a0)
*
lea.l redraw,a2
move.l a2,vector(a0) Provide code address
move.l d7,marker(a0) Add signature
move.b #2,prefix+limit(a0) Update every other field
move.b #1,prefix+count(a0)
move.b #0,prefix+missed(a0) Not currently used...
move.b #0,prefix+busy(a0)
move.b #8,prefix+chunks(a0) Scan 8 x 2K per update
move.b #0,prefix+soFar(a0)
move.b #0,prefix+flash_now(a0)
move.b #FLASH_PERIOD,prefix+flash_tick(a0)
* move.b #0,prefix+flash_rate(a0)
* Only turn flash on by default if running a 68040 or better?
move.l a0,a3 Save A0 for later
* moveq #0,d0
* trap #1 MT.INF
* move.b 161(a0),d0 Check CPU version
* cmp.b #$40,d0 < 040
* bcs.s too_old
move.b #FLASH_PERIOD,prefix+flash_rate(a3)
too_old:
move.l a3,a0
moveq #28,d0 Set up MT.LPOLL trap
trap1_out:
trap #1
it_worked:
moveq #0,d0
rts
*
find_pos2:
bsr find_pos Extra call for trapping
oops rts
*
* ACE_OFF is pretty simple too
*
mblit_off:
bsr.s find_pos2 Is our interrupt linked?
bmi.s it_worked If not, return at once
*
* Remove interrupt server and deallocate linkage memory
*
bsr blt_cop
*
not_opened:
lea.l -prefix(a4),a0
moveq #29,d0 MT.RPOLL trap key
trap #1
moveq #25,d0 MT.RECHP trap key
bra.s trap1_out
*
* ACE_FLASH 0 turns flash off. Parameters >0 set rate in frames before
* change, e.g. 25 to flash on and off once every second, 5 for 5 flashes
* per second, etc. Maximum 250 (change every 5 seconds, flash every 10).
*
flashrate:
move.w CA.GTINT,a2 Integer fetch vector
jsr (a2)
bne.s no_luck
subq.w #1,d3
bne.s bad_param
move.w 0(a1,a6.l),d5
cmp.w #251,d5
bcc.s bad_param
bsr.s find_pos
move.b d5,flash_rate(a4)
tst.b d5
bne.s it_worked
clr.b flash_now(a4)
bra.s it_worked
*
bad_param:
moveq #-15,d0 ERR.BP code
no_luck:
rts
*
setrate:
move.w CA.GTINT,a2 Integer fetch vector
jsr (a2)
bne.s no_luck
subq.w #2,d3
bne.s bad_param
*
* Check first parameter, number of 2K chunks to update each time
*
move.w 0(a1,a6.l),d4
ble.s bad_param
cmp.w #16,d4
bhi.s bad_param
*
* Check second parameter, delay between updates in fields
*
tst.b 2(a1,a6.l)
bne.s bad_param Reject if <0 or >255
move.b 3(a1,a6.l),d3
beq.s bad_param Trap zero (aka 256!)
*
bsr.s find_pos
*
move.b d3,limit(a4)
move.b d4,chunks(a4)
move.b #1,count(a4) Respond next field
bra.s it_worked
*
* ACE_STEP% returns the current setting of CHUNKS to SuperBASIC
*
step:
bsr.s find_pos
moveq #0,d4
move.b chunks(a4),d4
bra.s chk_integer
*
* ACE_FLASH% returns the current flash rate (default 16)
*
flash:
bsr.s find_pos
moveq #0,d4
move.b flash_rate(a4),d4
bra.s chk_integer
*
* ACE_RATE% returns the current setting of LIMIT to SuperBASIC
*
rate:
bsr.s find_pos
moveq #0,d4
move.b limit(a4),d4
*
* Return the integer in D4.W to SuperBASIC via the RI stack
*
chk_integer:
moveq #2,d1 Number of bytes needed
move.w BV.CHRIX,a2 Find the BV.CHRIX vector
jsr (a2) Allocate RI space
subq.l #2,$58(a6) Update BV.RIP
ret_integer:
move.l $58(a6),a1 Get BV.RIP
move.w d4,0(a1,a6.l) Stack the result
moveq #3,d4 Type = 16 bit Integer
no_error:
moveq #0,d0 No run-time error
rts
*
* FIND_POS points A4 at ACE variables in the interrupt list
*
* LONG link address
* LONG code address
* LONG "ACE3" marker
* BYTE count
* BYTE limit
*
* Result in A4, "ACEn" marker in D7; job ID in D1, uses D0
* Returns NOT FOUND to prior caller if the server is absent
*
find_pos:
moveq #0,d0 MT.INF
trap #1
move.l #'ACE3',d7
lea.l 60(a0),a4 Locate polled list
find_loop:
move.l (a4),d0
beq.s not_found Report to prior caller
*
movea.l d0,a4
cmp.l marker(a4),d7 Check signature
bne.s find_loop
*
found_it:
lea.l prefix(a4),a4 Point at the data
rts
*
not_found:
addq.l #4,a7 Discard return address
moveq #-7,d0 ERR.NF report code
rts
*
* Mode 8 byte conversion table, generated by ACE3_BAS
*
* Index: 0..255 A B C D E F G H
* Result: 0..255 B D F H A C E G
*
byteTable:
dc.b 0,16,1,17,32,48,33,49
dc.b 2,18,3,19,34,50,35,51
dc.b 64,80,65,81,96,112,97,113
dc.b 66,82,67,83,98,114,99,115
dc.b 4,20,5,21,36,52,37,53
dc.b 6,22,7,23,38,54,39,55
dc.b 68,84,69,85,100,116,101,117
dc.b 70,86,71,87,102,118,103,119
dc.b 128,144,129,145,160,176,161,177
dc.b 130,146,131,147,162,178,163,179
dc.b 192,208,193,209,224,240,225,241
dc.b 194,210,195,211,226,242,227,243
dc.b 132,148,133,149,164,180,165,181
dc.b 134,150,135,151,166,182,167,183
dc.b 196,212,197,213,228,244,229,245
dc.b 198,214,199,215,230,246,231,247
dc.b 8,24,9,25,40,56,41,57
dc.b 10,26,11,27,42,58,43,59
dc.b 72,88,73,89,104,120,105,121
dc.b 74,90,75,91,106,122,107,123
dc.b 12,28,13,29,44,60,45,61
dc.b 14,30,15,31,46,62,47,63
dc.b 76,92,77,93,108,124,109,125
dc.b 78,94,79,95,110,126,111,127
dc.b 136,152,137,153,168,184,169,185
dc.b 138,154,139,155,170,186,171,187
dc.b 200,216,201,217,232,248,233,249
dc.b 202,218,203,219,234,250,235,251
dc.b 140,156,141,157,172,188,173,189
dc.b 142,158,143,159,174,190,175,191
dc.b 204,220,205,221,236,252,237,253
dc.b 206,222,207,223,238,254,239,255
*
* SuperBASIC extension details for the BP.INIT vector
*
define dc.w 4+1 Four procedures
dc.w mblit_off-*
dc.b 7,'ACE_OFF'
dc.w mblit_on-*
dc.b 6,'ACE_ON'
dc.w setrate-*
dc.b 12,'ACE_PRIORITY' Long name hence +1
dc.w flashrate-*
dc.b 9,'ACE_FLASH'
dc.w 0
*
dc.w 3+1 Two verbose functions
dc.w rate-*
dc.b 9,'ACE_RATE%'
dc.w flash-*
dc.b 10,'ACE_FLASH%'
dc.w step-*
dc.b 9,'ACE_STEP%'
dc.w 0
*
end